package com.yzy.fly.enums;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Stream;

public interface IBaseEnum<T> {

    default void initEnum(T code, String msg) {
        EnumContainer.putEnum(this, code, msg);
    }

    default T getCode() {
        return EnumContainer.getEnum(this).getCode();
    }

    default String getMsg() {
        return EnumContainer.getEnum(this).getText();
    }


    //通过code获取枚举实例
    static <T, R extends IBaseEnum<T>> R getByCode(Class<? extends IBaseEnum<T>> clazz, T code) {
        return Stream.of(clazz.getEnumConstants())
                .filter(tEnumBean -> tEnumBean.getCode().equals(code)).map(v -> (R) v).findAny().orElse(
                        null);
    }

    static <T, R extends IBaseEnum<T>> R getByMsg(Class<? extends IBaseEnum<T>> clazz, String msg) {
        return Stream.of(clazz.getEnumConstants())
                .filter(tEnumBean -> tEnumBean.getMsg().equals(msg)).map(v -> (R) v).findAny().orElse(
                        null);
    }

    static <T, R extends IBaseEnum<T>> R getByStartsWithMsg(Class<? extends IBaseEnum<T>> clazz, String msg) {
        return Stream.of(clazz.getEnumConstants())
                .filter(tEnumBean -> msg.startsWith(tEnumBean.getMsg())).map(v -> (R) v).findAny().orElse(
                        null);
    }

    static <T, R extends IBaseEnum<T>> R getByEndsWithMsg(Class<? extends IBaseEnum<T>> clazz, String msg) {
        return Stream.of(clazz.getEnumConstants())
                .filter(tEnumBean -> msg.endsWith(tEnumBean.getMsg())).map(v -> (R) v).findAny().orElse(
                        null);
    }

    /**
     * 自定义函数比较过滤
     * @param clazz
     * @param msg
     * @param <T>
     * @param <R>
     * @return
     */
    static <T, R extends IBaseEnum<T>> R getByCustomWithMsg(Class<? extends IBaseEnum<T>> clazz, String msg, BiFunction<String, String, Boolean> function) {
        return Stream.of(clazz.getEnumConstants())
                .filter(tEnumBean -> function.apply(msg, tEnumBean.getMsg())).map(v -> (R) v).findAny().orElse(
                        null);
    }

    static <T, R extends IBaseEnum<T>> R getByCustomWithCode(Class<? extends IBaseEnum<T>> clazz, String code, BiFunction<String, T, Boolean> function) {
        return Stream.of(clazz.getEnumConstants())
                .filter(tEnumBean -> function.apply(code, tEnumBean.getCode())).map(v -> (R) v).findAny().orElse(
                        null);
    }

    //容器，用于存储枚举值
    class EnumContainer {
        private static final Map<IBaseEnum, EnumBean> ENUM_MAP = new ConcurrentHashMap();

        public static <T> void putEnum(IBaseEnum<T> baseEnum, T code, String msg) {
            ENUM_MAP.put(baseEnum, new EnumBean(code, msg));
        }

        static <K extends IBaseEnum<T>, T> EnumBean<T> getEnum(K dict) {
            return ENUM_MAP.get(dict);
        }

    }

    class EnumBean<T> {
        private final T code;
        private final String text;

        public EnumBean(T code, String text) {
            this.code = code;
            this.text = text;
        }

        public T getCode() {
            return this.code;
        }

        public String getText() {
            return this.text;
        }

        @Override
        public String toString() {
            return "EnumBean{" +
                    "code=" + code +
                    ", text='" + text + '\'' +
                    '}';
        }
    }
}